import { Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcrypt';
import { UsersService } from '../users/users.service';
import { LoginDto } from './dto/login.dto';
import { RegisterDto } from './dto/register.dto';
import { JwtPayload } from './interfaces/jwt-payload.interface';
import { User } from '../users/entities/user.entity';

/**
 * 认证服务
 * 处理用户登录、注册等认证相关业务逻辑
 */
@Injectable()
export class AuthService {
  constructor(
    private readonly usersService: UsersService,
    private readonly jwtService: JwtService,
  ) {}

  /**
   * 用户登录
   * @param loginDto 登录信息
   * @returns 包含访问令牌和用户信息的对象
   */
  async login(loginDto: LoginDto) {
    const { usernameOrEmail, password } = loginDto;
    
    // 根据用户名或邮箱查找用户
    let user: User | null = null;
    
    if (usernameOrEmail.includes('@')) {
      user = await this.usersService.findByEmail(usernameOrEmail);
    } else {
      user = await this.usersService.findByUsername(usernameOrEmail);
    }
    
    if (!user) {
      throw new UnauthorizedException('用户名或密码错误');
    }
    
    // 验证密码
    const isPasswordValid = await bcrypt.compare(password, user.password);
    if (!isPasswordValid) {
      throw new UnauthorizedException('用户名或密码错误');
    }
    
    // 检查用户是否被禁用
    if (!user.isActive) {
      throw new UnauthorizedException('用户已被禁用');
    }
    
    // 生成JWT令牌
    const payload: JwtPayload = {
      sub: user.id,
      username: user.username,
      email: user.email,
    };
    
    const accessToken = this.jwtService.sign(payload);
    
    // 返回令牌和用户信息（不包含密码）
    const { password: _, ...userInfo } = user;
    
    return {
      accessToken,
      user: userInfo,
    };
  }

  /**
   * 用户注册
   * @param registerDto 注册信息
   * @returns 新创建的用户信息
   */
  async register(registerDto: RegisterDto) {
    // 创建用户
    const user = await this.usersService.create(registerDto);
    
    // 返回用户信息（不包含密码）
    const { password: _, ...userInfo } = user;
    
    return userInfo;
  }

  /**
   * 验证用户
   * @param usernameOrEmail 用户名或邮箱
   * @param password 密码
   * @returns 用户信息或null
   */
  async validateUser(usernameOrEmail: string, password: string): Promise<User | null> {
    let user: User | null = null;
    
    if (usernameOrEmail.includes('@')) {
      user = await this.usersService.findByEmail(usernameOrEmail);
    } else {
      user = await this.usersService.findByUsername(usernameOrEmail);
    }
    
    if (user && await bcrypt.compare(password, user.password)) {
      return user;
    }
    
    return null;
  }
}